package com.pan.utils;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public enum ScanTools {

    INSTANCE;
    private ClassLoader classLoader;

    private Pattern packPattern;
    private File startScanDir;




    public void init(Class startClass){
        String packageName = startClass.getPackage().getName();
        classLoader = startClass.getClassLoader();

        String packPath = packageName.replaceAll("\\.", "/");
        URL url = classLoader.getResource(packPath);
        startScanDir = new File(url.getFile());
        if (!startScanDir.exists()){
            //获取系统字符编码
            Charset charset = Charset.defaultCharset();
            try {
                String path = url.getFile();
                //用系统字符编码解码
                for ( String newPath = URLDecoder.decode(path, charset.toString());
                      newPath.length()<path.length();
                     newPath = URLDecoder.decode(newPath,charset.toString())){
                    path = newPath;
                }
                startScanDir = new File(path);
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }

        packPattern = Pattern.compile(packageName.replaceAll("\\.","\\\\\\\\")+"\\\\.+(?=\\.class$)");
    }

    private String getFullName(String filePath){
        Matcher matcher = packPattern.matcher(filePath);
        if (matcher.find()) {
            String fullName = matcher.group();
            return fullName.replaceAll("\\\\","\\.");
        }else {
            return null;
        }
    }

    public List<Class> getAllClass(){
        return getAllClass(startScanDir);
    }

    private List<Class> getAllClass(File file){
        List<Class> result = new ArrayList<>();
        for (File f: file.listFiles()) {
            if (f.isDirectory()) {
                result.addAll(getAllClass(f));
            } else if (f.getAbsolutePath().endsWith(".class")) {
                String fullName = getFullName(f.getAbsolutePath());
                Class<?> clazz = null;
                try {
                    clazz = classLoader.loadClass(fullName);
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
                result.add(clazz);

            }
        }
        return result;
    }
}
